package br.ufes.ceunes.poo.model.pojo;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.Table;

/**
 * Classe para objetos do tipo Pedido, onde serão contidos, valores,
 * identificadores e métodos para o mesmo.
 */
@Entity
@Table(name="pedidos")
public class Pedido implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "pedido_id")
    private Integer id;

    @ElementCollection
    @CollectionTable(name = "carrinho", joinColumns = @JoinColumn(name = "pedido_id"))
    @MapKeyJoinColumn(name = "produto_id", referencedColumnName = "id")
    @Column(name = "quantidade", nullable = false)
    private Map<Produto, Integer> carrinho;

    @Column(nullable = false)
    private Double subtotal;

    @Column(name = "status_venda", nullable = false)
    private Boolean vendaPaga;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "clienteId")
    private Cliente cliente;

    /**
     * Método para calcular o subtotal do Pedido
     *
     * @param valor - valor atribuido ao subtotal
     */
    public void calcularSubtotal(Double valor) {
        subtotal = valor;
    }

    /**
     * Método para retornar o subtotaldo Pedido
     *
     * @return Double - subtotal - subtotal do Pedido
     */
    public Double getSubTotal() {
        return subtotal;
    }

    /**
     * Método para retornar o status do Pedido
     *
     * @return boolean
     */
    public Boolean getStatus() {
        return vendaPaga;
    }

    /**
     * Método para aterar o status do Pedido
     *
     * @param s - status atribuido ao Pedido
     */
    public void setStatus(Boolean s) {
        vendaPaga = s;
    }

    /**
     * Contrutor do Pedido Subtotal é zero, status da venda é false pois não há
     * produtos no carrinho
     */
    public Pedido() {
        carrinho = new HashMap<Produto, Integer>();
        vendaPaga = false;
        subtotal = 0.0;
    }

    /**
     * Método para alterar status do Pedido
     *
     * Objetivo : Ele é usado para alterar o status se a compra for efetuada ou
     * não.
     *
     * @param alteraStatus booleano que define o status
     */
    public void alterarStatus(Boolean alteraStatus) {
        vendaPaga = alteraStatus;
    }

    /**
     * Método para adicionar um produto na lista de Pedidos
     *
     * @param produto - produto que será adicionado na lista de pedidos
     */
    public void adicionarProduto(Produto produto) {
        adicionarProduto(produto, 1);
    }

    /**
     * Método para adicionar um produto e sua quantidade na lista de Pedidos
     *
     * @param produto - produto que será adicionado na lista de pedidos
     * @param quantidade - quantidade do produto adicionado na lista de Pedidos
     */
    public void adicionarProduto(Produto produto, Integer quantidade) {
        if (carrinho.containsKey(produto)) {
            carrinho.put(produto, carrinho.get(produto) + quantidade);
        } else {
            carrinho.put(produto, quantidade);
        }
        if (produto.getPreco() != null) {
            subtotal += produto.getPreco() * quantidade;
        }
    }

    /**
     * Método para retornar a quantidade de produtos de um produto existente na
     * lista de Pedidos
     *
     * @param produto - produto buscado na lista de Pedidos
     * @return Integer - 0 se não encontrar, quantidade do produto caso
     * contrario
     */
    public Integer getQuantidade(Produto produto) {
        if (carrinho.containsKey(produto)) {
            return carrinho.get(produto);
        }
        return 0;
    }

    /**
     * Método para retornar o lista de Pedidos
     *
     * @return Map - relação produto quantidade
     */
    public Map<Produto, Integer> getCarrinho() {
        return carrinho;
    }

    /**
     * Método para a quantidade de um produto da lista de pedidos
     *
     * @param produto - produto buscado na lista de pedidos
     * @param quantidade - quantidade do produto que se deseja reduzir
     */
    public void removerQuantidade(Produto produto, Integer quantidade) {
        if (carrinho.containsKey(produto)) {
            int quant = carrinho.get(produto);
            quant -= quantidade;
            if (quant < 0) {
                quant = 0;
                carrinho.remove(produto);
            } else {
                carrinho.put(produto, quant);
            }
            subtotal -= produto.getPreco() * quantidade;
        }
    }

    /**
     * Método para retornar o ID do pedido
     *
     * @return Integer id - idetentificador do Pedido
     */
    public Integer getId() {
        return id;
    }

    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }

    public Cliente getCliente() {
        return cliente;
    }

    /**
     * Método para alterar o ID do Pedido
     *
     * @param id - identificador do Pedido
     */
    public void setId(Integer id) {
        if (this.id == null) {
            this.id = id;
        }
    }

}
